﻿using Microsoft.SharePoint;
using SPCoder.Utils.Nodes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace SPCoder.Windows
{
    public partial class Explorer : DockContent
    {
        public Explorer()
        {
            InitializeComponent();
        }
        
        public List<BaseNode> Nodes = new List<BaseNode>();
        public SPSite Site;

        public void DisposeNodes()
        {
            foreach (TreeNode treeNode in tvSp.Nodes)
            {
                DisposeNode(treeNode);
            }

            foreach (BaseNode node in Nodes)
            {
                DisposeBaseNodes(node);
            }
        }

        private void DisposeNode(TreeNode node)
        {
            if (node != null)
            {
                if (node.Tag != null && node.Tag is IDisposable)
                {
                    try
                    {
                        ((IDisposable)node.Tag).Dispose();
                    }
                    catch (Exception)
                    {
                        //just skip this
                    }
                }

                foreach (TreeNode treeNode in node.Nodes)
                {
                    DisposeNode(treeNode);
                }
            }
        }

        private void DisposeBaseNodes(BaseNode node)
        {
            if (node != null)
            {
                if (node != null && node.SPObject != null && node.SPObject is IDisposable)
                {
                    try
                    {
                        ((IDisposable)node.SPObject).Dispose();
                    }
                    catch (Exception)
                    {
                        //just skip this
                    }
                }

                foreach (BaseNode treeNode in node.Children)
                {
                    DisposeBaseNodes(treeNode);
                }
            }
        }

        private string _currentSiteUrl;
        private bool _workerFree = true;
        public void Connect(string siteUrl)
        {
            //_currentSiteUrl = siteUrl;
            //backgroundWorker1.RunWorkerAsync();
            //moved all to background worker
            Site = new SPSite(siteUrl);
            BaseNode rootNode = new SPSiteNode(Site);
            rootNode.SPObject = Site;

            doSPWeb(Site.RootWeb, rootNode, rootNode);//, root);

            //Now create tree view stuff;
            CreateAllTreeViewNodes(rootNode);
            //Nodes
        }

        private void CreateAllTreeViewNodes(BaseNode rootNode)
        {
            TreeNode root = CreateNode(rootNode.Title, "", rootNode);
            
            tvSp.Nodes.Add(root);

            CreateTreeViewNode(root, rootNode.Children[0]);
        }

        private void CreateTreeViewNode(TreeNode tvNode, BaseNode node)
        {
            TreeNode myNode = CreateNode(node.Title, node.Icon, node);
            tvNode.Nodes.Add(myNode);
            foreach (BaseNode child in node.Children)
            {
                CreateTreeViewNode(myNode, child);
            }
        }

        private TreeNode CreateNode(string tekst, string imageUrl, Object o)
        {
            string[] s = imageUrl.Split('/');
            if (s.Length > 0)
                imageUrl = s[s.Length - 1];
            TreeNode node = new TreeNode { Text = tekst, Tag = o, ImageKey = imageUrl };
            return node;
        }

        private void doSPWeb(SPWeb web, BaseNode parentNode, BaseNode rootNode)//, TreeNode root)
        {
            //TreeNode node = CreateNode(web.Title, "", web);
            //root.Nodes.Add(node);

            BaseNode myNode = new SPWebNode(web);
            parentNode.Children.Add(myNode);
            myNode.ParentNode = parentNode;
            myNode.RootNode = rootNode;

            foreach (SPWeb childWeb in web.Webs)
            {
                doSPWeb(childWeb, myNode, rootNode);
            }

            foreach (SPList list in web.Lists)
            {
                BaseNode myListNode = new SPListNode(list);
                myNode.Children.Add(myListNode);
                myListNode.ParentNode = myNode;
                myListNode.RootNode = rootNode;
                //TreeNode lnode = CreateNode(list.Title, list.ImageUrl, list);
                //node.Nodes.Add(lnode);
            }
            web.Dispose();
        }

        private void tvSp_ItemDrag(object sender, ItemDragEventArgs e)
        {
            try
            {                
                //sourceNode = (TreeNode)e.Item;
                SPCoderForm.MainForm.DragedBaseNode = ((TreeNode)e.Item).Tag as BaseNode;
                if (SPCoderForm.MainForm.DragedBaseNode != null && SPCoderForm.MainForm.DragedBaseNode.SPObject != null)
                {
                    tvSp.DoDragDrop(SPCoderForm.MainForm.DragedBaseNode.SPObject, DragDropEffects.Copy | DragDropEffects.Move);
                }

            }
            catch (Exception)
            {
                //this can happen when user tries to drop object to source window
                //just ignore that exception
            }
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            Connect(txtUrl.Text);
        }

        private void tvSp_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                _workerFree = false;
                Site = new SPSite(_currentSiteUrl);
                BaseNode rootNode = new SPSiteNode(Site);
                rootNode.SPObject = Site;

                doSPWeb(Site.RootWeb, rootNode, rootNode);//, root);

                //Now create tree view stuff;
                CreateAllTreeViewNodes(rootNode);
                //Nodes
                _workerFree = true;
            }
            catch (Exception exc)
            {
                //Log this
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _workerFree = true;
        } 
    }
}
